package com.macro.mall.portal.config.sharding;

import cn.hutool.core.util.HashUtil;
import cn.hutool.setting.dialect.Props;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;

import java.util.Collection;

/**
 * @author wwj
 */
@Slf4j
public class CustomPreciseTableShardingAlgorithm implements PreciseShardingAlgorithm<Long> {

    private static int virtualNodeCount;

    private static String virtualNodeCountRang;




    @Override
    public String doSharding(Collection<String> tableNames, PreciseShardingValue<Long> preciseShardingValue) {

        Props props = new Props("application-shardingJDBC.properties");
        virtualNodeCount = props.getInt(ShardingConstant.SHARDING_TABLE_VIRTUAL_NODE_COUNT);
        virtualNodeCountRang = props.getStr(ShardingConstant.SHARDING_TABLE_VIRTUAL_NODE_COUNT_RANG);

        int hash = HashUtil.rsHash(preciseShardingValue.getValue() + "");
        // 根据用户名的hash值对《virtualNodeCount》进行取余后，得到余数，余数一定在0，《virtualNodeCountRang》之间的
        Integer mod = hash % virtualNodeCount;

        // 由于获取的字符串的hash值可能存在负数，所以需要需要取其绝对值
        mod = ShardingUtils.getAbsoluteValue(mod);

        // 虚拟节点范围映射到实际物理节点
        Integer shardingValue = ShardingUtils.getPhysicNodeByVisualNode(mod, virtualNodeCountRang);

        for (String each : tableNames) {
            // 将余数与配置的实际表名进行匹配
            if (each.endsWith(String.valueOf(shardingValue))) {
                log.info("logic table : {}", each);
                return each;
            }
        }
        throw new UnsupportedOperationException();
    }
}
